В Украине, как известно, существует множество проблем,
и одна из них — состояние дорог. Новый президент страны решил сосредоточиться
на развитии дорожной инфраструктуры. Его цель — построить дополнительные дороги
между городами так, чтобы из любого города можно было добраться до любого
другого (возможно, через промежуточные населённые пункты, не обязательно
напрямую). Разумеется, при этом необходимо построить как можно меньше новых
дорог.
Предположим, что все дороги в Украине являются
двусторонними (как уже существующие, так и те, которые предстоит построить), то
есть движение по ним возможно в обоих направлениях. При этом между двумя
городами может быть несколько дорог, а также могут существовать дороги, ведущие
из города в сам себя.
Вход. Первая строка содержит два
натуральных числа
n и m (1 ≤
n, m ≤ 10000) – количество городов и количество
уже существующих дорог. В следующих m строках записаны по два целых числа ai и bi (1 ≤ ai, bi ≤ n)
– номера городов, соединённых существующей дорогой.
Выход. Выведите минимальное количество дорог, которые
необходимо построить, чтобы из любого города можно было добраться до любого
другого.
Пример входа |
Пример выхода |
7 5 1 3 2 3 3 2 2 4 6 7 |
2 |
графы – поиск в глубину
Анализ алгоритма
Поскольку граф содержит 10000 вершин, для его хранения будем использовать
список смежности. На основе входного списка рёбер построим соответствующее
представление графа. Затем с помощью поиска в глубину определим количество
компонент связности. Число новых дорог, которые необходимо построить, будет
равно количеству компонент связности минус один.
Пример
Граф, приведённый в примере, имеет
следующий вид:
Граф состоит из трёх компонент
связности. Чтобы объединить их в одну, достаточно добавить два ребра.
Объявим список смежности g и массив used,
в котором будем отмечать посещённые вершины.
vector<vector<int> > g;
vector<int> used;
Функция dfs совершает поиск в глубину, начиная с вершины v.
void dfs(int v)
{
used[v] = 1;
for (int to : g[v])
if (!used[to]) dfs(to);
}
Основная часть
программы. Читаем входные данные.
scanf("%d %d", &n, &m);
g.resize(n
+ 1);
Читаем m ребер, строим список смежности графа.
for (i = 1; i <= m; i++)
{
scanf("%d %d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}
Выполняем поиск в
глубину на несвязном графе. В переменной cnt подсчитываем количество
компонент связности.
used.resize(n
+ 1);
cnt
= 0;
for (i = 1; i <= n; i++)
if (used[i] == 0)
{
dfs(i);
cnt++;
}
Выводим количество
дорог, которые необходимо построить.
printf("%d\n", cnt - 1);
#include <stdio.h>
#define MAX 10001
int mas[MAX];
int Repr(int n)
{
while (n != mas[n]) n = mas[n];
return n;
}
void Union(int x, int y)
{
int x1 = Repr(x), y1 = Repr(y);
if (x1 == y1) return;
mas[x1] = y1;
}
int a, b, i, j, n, m, count;
int main(void)
{
scanf("%d
%d", &n, &m);
for (i = 1; i
<= n; i++) mas[i] = i;
for (i = 0; i <
m; i++)
{
scanf("%d
%d", &a, &b);
Union(a, b);
}
count = 0;
for (i = 1; i
<= n; i++)
if (mas[i] == i)
count++;
printf("%d\n", count - 1);
return 0;
}
import java.util.*;
public class Main
{
static ArrayList<Integer>[] g;
static boolean used[];
static int n, m;
static void
dfs(int v)
{
used[v] = true;
for(int i = 0; i < g[v].size(); i++)
{
int to = g[v].get(i);
if (used[to] == false) dfs(to);
}
}
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
n = con.nextInt();
m = con.nextInt();
used = new boolean[n+1];
g = new ArrayList[n+1];
for(int i = 0; i <= n; i++)
g[i] = new
ArrayList<Integer>();
for (int i = 0; i < m; i++)
{
int a = con.nextInt();
int b = con.nextInt();
g[a].add(b);
g[b].add(a);
}
int cnt = 0;
for(int i = 1; i <= n; i++)
if (used[i] == false)
{
dfs(i);
cnt++;
}
System.out.println(cnt - 1);
con.close();
}
}
import sys
sys.setrecursionlimit(1000000)
Функция dfs совершает поиск в глубину, начиная с вершины v.
def dfs(v):
used[v] = 1
for to in g[v]:
if not used[to]:
dfs(to)
Основная часть программы. Читаем входные данные.
n, m = map(int, input().split())
g = [[] for _ in range(n + 1)]
used = [0] * (n + 1)
Читаем m ребер, строим список смежности графа.
for _ in range(m):
a, b = map(int, input().split())
g[a].append(b)
g[b].append(a)
Выполняем поиск в глубину на несвязном графе. В
переменной cnt подсчитываем количество компонент связности.
cnt = 0
for i in range(1, n + 1):
if not used[i]:
dfs(i)
cnt += 1
Выводим количество дорог, которые необходимо
построить.
print(cnt - 1)